/*
 * $Id: TransactionController.java,v 1.6 2009/11/02 03:45:11 afaichun Exp $
 * 
 * Copyright (C) 2008 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.processor.iptds.transaction;

import org.springframework.util.Assert;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.dbLogger.StepLogger;
import com.ge.healthcare.autosc.processor.exception.ClientDrvCommandException;
import com.ge.healthcare.autosc.processor.exception.IPTDSException;
import com.ge.healthcare.autosc.processor.iip.comm.ClientDrvCommand;
import com.ge.healthcare.autosc.processor.iptds.IPTDSSocketHandler;
import com.ge.healthcare.autosc.processor.iptds.IPTDSSystemInfo;
/**
 * 
 * @author 212042946
 *
 */
public class TransactionController {
	
	private ICHFTransaction iCHFTransaction = null;
	
	public void init() {
		Assert.notNull(iCHFTransaction, 
				"CHFTransaction is not defined. Please use setCHFTransaction to provide one.");
	}
	
	/**
	 * Start the IPTDS file transfer transaction
	 * @param socketHandler
	 * @param systemInfo
	 * @return true/false indicate if the whole IPTDS transaction is considered as success or failure.
	 * 			Failure means error has occurred during the transaction process.
	 */
	public void startTransaction(IPTDSSocketHandler socketHandler, IPTDSSystemInfo systemInfo) 
		throws IPTDSException {

		boolean success = true;
		Long batchId = null;
	
		ASCLogger.debug(this.getClass(), "startTransaction", 
				"Start transaction from controller. System " + systemInfo.getSystemId());
		// move to clientdrv communication
		ClientDrvCommand clientDrv = socketHandler.moveConnectionToClientDrv();
		
		try {
			do {
				batchId = 
					iCHFTransaction.executeTransaction(batchId, systemInfo, clientDrv);
				
			} while(batchId != null);
		} catch (IPTDSException iptdse) {
			success = false;
			ASCLogger.error(this.getClass(), "startTransaction",
					"IPTDS transaction declared as failed with exception.", iptdse);
			throw iptdse;
		} catch (RuntimeException re) {
			success = false;
			ASCLogger.fatal(this.getClass(), "startTransaction",
					"IPTDS transaction controller got runtime exception. System " + 
					systemInfo.getSystemId(), re);
			throw re;
		} finally {
			//Close IPTDS communication transaction
			exitTransaction(clientDrv, systemInfo, success);
			ASCLogger.debug(this.getClass(), "startTransaction", 
					"Exit transaction from controller. System " + systemInfo.getSystemId());
		}
	}
	
	public void setCHFTransaction(ICHFTransaction transaction) {
		this.iCHFTransaction = transaction;
	}
	
	private void exitTransaction(ClientDrvCommand clientDrv, 
			IPTDSSystemInfo systemInfo, boolean success) throws IPTDSException {
		String methodName = "closeTransaction";
		try {
			if(success) {
				StepLogger.addStepLog("Close IPTDS with success.");
				clientDrv.executeExitSuccessCommand();
			} else {
				StepLogger.addStepLog("Close IPTDS with failure.");
				failedTransaction(clientDrv);
				clientDrv.executeExitFailCommand();
			}
		} catch (ClientDrvCommandException cdce) {
			String errMsg = new StringBuffer()
				.append("Failed issueing clientdrv exit command to the remote system.")
				.append("SystemInfo:\n")
				.append(systemInfo.toString()).toString();
			ASCLogger.error(this.getClass(), methodName, errMsg, cdce);
			throw new IPTDSException(cdce);
		}
	}
	
	private void failedTransaction(ClientDrvCommand clientDrv) 
		throws IPTDSException {
		try {
			clientDrv.executeStandbyCommand(24);
		} catch (ClientDrvCommandException cdce) {
			ASCLogger.error(this.getClass(), "failedTranscation", 
					"Failed issuing clientdrv standby command for 24 hours", cdce);
			throw new IPTDSException(cdce);
		}
	}
}
